package systembasicconfiglogic

import (
	"context"
	"errors"
	"fmt"
	"github.com/zeromicro/go-zero/core/logx"
	"os"
	"yunzhan/common/models"
	utils "yunzhan/common/utils"
	"yunzhan/rpc-server/internal/svc"
	agent "yunzhan/rpc-server/pb"
)

type SystemParameterConfigLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewSystemParameterConfigLogic(ctx context.Context, svcCtx *svc.ServiceContext) *SystemParameterConfigLogic {
	return &SystemParameterConfigLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

// SystemParameterConfig 系统级参数配置
func (l *SystemParameterConfigLogic) SystemParameterConfig(in *agent.SystemBasicConfigRequest) (*agent.DeployResponse, error) {
	if in.NodeInfo == nil {
		return &agent.DeployResponse{
			Code:    500,
			Message: "未配置节点信息, 无法执行系统级参数配置",
		}, errors.New("未配置节点信息, 无法执行系统级参数配置")
	}

	step := 1
	// 创建 LogManager 实例
	logManager := models.NewLogManager(100, fmt.Sprintf("http://%s:%d/v1/log/add", l.svcCtx.Config.RestServices["apiServer"].RestConf.Host, l.svcCtx.Config.RestServices["apiServer"].RestConf.Port))
	defer logManager.Close()

	// 用于保存每个参数的状态
	paramStatus := make(map[string]string)

	execAndLog := func(cmd, successMsg, failureMsg string, param string) (string, error) {
		output, err := utils.ExecCommand(cmd)
		if err != nil {
			logManager.SendLog(in.ClusterID, in.NodeInfo.Host, step, "ERROR", fmt.Sprintf("%s: %v", failureMsg, err), "SystemParameterConfig", "Client")
			return "", err
		}
		logManager.SendLog(in.ClusterID, in.NodeInfo.Host, step, "INFO", fmt.Sprintf("%s: %s", successMsg, output), "SystemParameterConfig", "Client")
		if param != "" {
			paramStatus[param] = output
		}
		step++
		return output, nil
	}

	commands := []struct {
		cmd         string
		successMsg  string
		failureMsg  string
		param       string
		conditionFn func() bool
	}{
		{"cat /sys/kernel/mm/transparent_hugepage/enabled", "Checked transparent hugepage enabled status", "Failed to check transparent hugepage enabled status", "", nil},
		{"cat /sys/kernel/mm/transparent_hugepage/defrag", "Checked transparent hugepage defrag status", "Failed to check transparent hugepage defrag status", "", nil},
		{"echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled", "Temporarily disabled transparent hugepage enabled", "Failed to temporarily disable transparent hugepage enabled", "Transparent Hugepage Enabled", nil},
		{"echo never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag", "Temporarily disabled transparent hugepage defrag", "Failed to temporarily disable transparent hugepage defrag", "Transparent Hugepage Defrag", nil},
	}

	// 检查系统环境
	isUbuntu, err := utils.CheckUbuntu()
	if err != nil {
		logManager.SendLog(in.ClusterID, in.NodeInfo.Host, step, "ERROR", fmt.Sprintf("检查系统环境时出错: %v", err), "SystemParameterConfig", "Client")
		return &agent.DeployResponse{Code: 500, Message: "Failed to check system environment"}, err
	}
	logManager.SendLog(in.ClusterID, in.NodeInfo.Host, step, "INFO", "Checked system environment", "SystemParameterConfig", "Client")
	step++

	if isUbuntu {
		commands = append(commands, struct {
			cmd         string
			successMsg  string
			failureMsg  string
			param       string
			conditionFn func() bool
		}{
			`sudo systemctl disable apparmor --now && sudo sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="\(.*\)"/GRUB_CMDLINE_LINUX_DEFAULT="\1 apparmor=0 transparent_hugepage=never"/' /etc/default/grub`,
			"Permanently disabled transparent hugepage on Ubuntu",
			"Failed to permanently disable transparent hugepage",
			"",
			nil,
		})
	} else {
		rcLocalContent := `
if test -f /sys/kernel/mm/transparent_hugepage/enabled; then
echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag; then
echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi
`

		commands = append(commands, struct {
			cmd         string
			successMsg  string
			failureMsg  string
			param       string
			conditionFn func() bool
		}{
			fmt.Sprintf("echo '%s' | sudo tee -a /etc/rc.d/rc.local", rcLocalContent),
			"Permanently disabled transparent hugepage on non-Ubuntu",
			"Failed to permanently disable transparent hugepage",
			"",
			nil,
		})

		commands = append(commands, struct {
			cmd         string
			successMsg  string
			failureMsg  string
			param       string
			conditionFn func() bool
		}{
			"getenforce",
			"Checked Selinux status",
			"Failed to check Selinux status",
			"",
			nil,
		})

		commands = append(commands, struct {
			cmd         string
			successMsg  string
			failureMsg  string
			param       string
			conditionFn func() bool
		}{
			"setenforce 0",
			"Temporarily disabled Selinux",
			"Failed to temporarily disable Selinux",
			"",
			func() bool {
				output, err := utils.ExecCommand("getenforce")
				return err == nil && output != "Disabled"
			},
		})

		commands = append(commands, struct {
			cmd         string
			successMsg  string
			failureMsg  string
			param       string
			conditionFn func() bool
		}{
			"sudo sed -i s/=enforcing/=disabled/ /etc/selinux/config",
			"Permanently disabled Selinux",
			"Failed to permanently disable Selinux",
			"",
			func() bool {
				_, err := os.Stat("/etc/selinux/config")
				return err == nil
			},
		})
	}

	// 添加其余命令
	commands = append(commands, []struct {
		cmd         string
		successMsg  string
		failureMsg  string
		param       string
		conditionFn func() bool
	}{
		{"ulimit -n 655356", "Temporarily modified file descriptor limit", "Failed to temporarily modify file descriptor limit", "File Descriptor Limit", nil},
		{
			fmt.Sprintf("echo '%s' | sudo tee -a /etc/security/limits.conf", `
* soft nofile 655356
* hard nofile 655356
* soft nproc 655356
* hard nproc 655356
`), "Permanently modified file descriptor and max user_logic processes limit", "Failed to permanently modify file descriptor and max user_logic processes limit", "", nil},
		{"sysctl vm.max_map_count", "Checked vm.max_map_count", "Failed to check vm.max_map_count", "", nil},
		{"sudo sysctl -w vm.max_map_count=2000000", "Temporarily modified vm.max_map_count", "Failed to temporarily modify vm.max_map_count", "VM Max Map Count", nil},
		{"echo 'vm.max_map_count=2000000' | sudo tee -a /etc/sysctl.conf", "Permanently modified vm.max_map_count", "Failed to permanently modify vm.max_map_count", "", nil},
		{"sysctl fs.file-max", "Checked fs.file-max", "Failed to check fs.file-max", "", nil},
		{"sysctl -w fs.file-max=6553556", "Temporarily modified fs.file-max", "Failed to temporarily modify fs.file-max", "FS File Max", nil},
		{"echo 'fs.file-max=6553556' | sudo tee -a /etc/sysctl.conf", "Permanently modified fs.file-max", "Failed to permanently modify fs.file-max", "", nil},
		{"sysctl vm.swappiness", "Checked vm.swappiness", "Failed to check vm.swappiness", "", nil},
		{"sysctl -w vm.swappiness=10", "Temporarily modified vm.swappiness", "Failed to temporarily modify vm.swappiness", "VM Swappiness", nil},
		{"echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf", "Permanently modified vm.swappiness", "Failed to permanently modify vm.swappiness", "", nil},
		{"sudo sysctl -p", "Sysctl settings applied successfully", "Failed to apply sysctl settings", "", nil},
	}...)

	// 执行所有命令
	for _, command := range commands {
		if command.conditionFn == nil || command.conditionFn() {
			if _, err := execAndLog(command.cmd, command.successMsg, command.failureMsg, command.param); err != nil {
				return &agent.DeployResponse{Code: 500, Message: command.failureMsg}, err
			}
		}
	}

	// 构建返回消息
	responseMessage := fmt.Sprintf("%s: 系统参数配置完成\n参数状态:\n", in.NodeInfo.Host)
	for param, status := range paramStatus {
		responseMessage += fmt.Sprintf("- %s: %s\n", param, status)
	}

	return &agent.DeployResponse{
		Code:    200,
		Message: responseMessage,
	}, nil
}
